from fastapi import APIRouter, HTTPException, UploadFile, File, Form
import os
import glob
import markdown
from fastapi import APIRouter, HTTPException
from utils.logger import logger
import shutil
from typing import Optional

router = APIRouter()

# 文档目录路径
DOCS_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "static", "md")
logger.info(f"DOCS_DIR: {DOCS_DIR}")

# 添加文件上传API
@router.post("/upload")
async def upload_document(
    file: UploadFile = File(...),
    title: Optional[str] = Form(None)
):
    """上传Markdown文档文件"""
    try:
        # 验证文件类型
        if not file.filename.endswith('.md'):
            raise HTTPException(status_code=400, detail="只支持上传Markdown(.md)文件")
        
        # 如果提供了标题，使用标题作为文件名，否则使用原始文件名
        filename = title + ".md" if title else file.filename
        
        # 确保文件名不包含非法字符
        import re
        filename = re.sub(r'[\\/:*?"<>|]', '_', filename)
        
        # 确保目录存在
        os.makedirs(DOCS_DIR, exist_ok=True)
        
        # 保存文件路径
        file_path = os.path.join(DOCS_DIR, filename)
        
        # 保存上传的文件
        with open(file_path, "wb") as buffer:
            shutil.copyfileobj(file.file, buffer)
        
        logger.info(f"文档上传成功: {filename}")
        
        # 返回成功信息
        return {
            "success": True,
            "message": "文档上传成功",
            "filename": filename,
            "path": file_path
        }
    except HTTPException as e:
        # 重新抛出HTTP异常
        raise e
    except Exception as e:
        logger.error(f"文档上传失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"文档上传失败: {str(e)}")


@router.get("/list")
async def get_document_list():
    """获取所有可用的文档列表"""
    try:
        from utils.logger import logger
        logger.info("获取文档列表")
        
        # 获取所有md文件
        md_files = []
        
        # 尝试使用相对路径（优先）
        rel_path = os.path.join("static", "md")
        if os.path.exists(rel_path):
            md_files = glob.glob(os.path.join(rel_path, "*.md"))
            logger.info(f"相对路径文档目录存在，包含文件: {[os.path.basename(f) for f in md_files]}")
        
        # 如果相对路径没有找到文件，尝试使用绝对路径
        if not md_files:
            if os.path.exists(DOCS_DIR):
                md_files = glob.glob(os.path.join(DOCS_DIR, "*.md"))
                logger.info(f"绝对路径文档目录存在，包含文件: {[os.path.basename(f) for f in md_files]}")
        
        # 构建文档列表
        documents = []
        for file_path in md_files:
            file_name = os.path.basename(file_path)
            doc_id = os.path.splitext(file_name)[0]
            
            # 使用文件名作为标题
            title = doc_id
            # 处理文件名，移除数字前缀（如"01_"、"1."等格式）
            import re
            title = re.sub(r'^\d+[_.-]\s*', '', title)
                
            documents.append({
                "id": doc_id,
                "title": title,
                "file_name": file_name
            })
        
        # 按标题排序
        documents.sort(key=lambda x: x["title"])
        logger.info(f"找到 {len(documents)} 个文档")
        
        return {"documents": documents}
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取文档列表失败: {str(e)}")

@router.get("/content/{doc_id}")
async def get_document_content(doc_id: str):
    """获取指定文档的内容"""
    try:
        from utils.logger import logger
        from urllib.parse import unquote
        
        # 确保文档ID正确解码（处理中文等非ASCII字符）
        decoded_doc_id = unquote(doc_id)
        logger.info(f"API请求文档内容: 原始ID={doc_id}, 解码后ID={decoded_doc_id}")
        
        # 获取所有可用的文档文件
        import glob
        md_files = []
        
        # 尝试使用相对路径（优先）
        rel_path = os.path.join("static", "md")
        if os.path.exists(rel_path):
            md_files = glob.glob(os.path.join(rel_path, "*.md"))
            logger.info(f"相对路径文档目录存在，包含文件: {[os.path.basename(f) for f in md_files]}")
        
        # 如果相对路径没有找到文件，尝试使用绝对路径
        if not md_files:
            if os.path.exists(DOCS_DIR):
                md_files = glob.glob(os.path.join(DOCS_DIR, "*.md"))
                logger.info(f"绝对路径文档目录存在，包含文件: {[os.path.basename(f) for f in md_files]}")
        
        # 记录所有可用文档的文件名（不含扩展名）
        available_docs = [os.path.splitext(os.path.basename(f))[0] for f in md_files]
        logger.info(f"可用文档列表: {available_docs}")
        
        # 尝试查找匹配的文档文件
        file_path = None
        
        # 1. 首先尝试直接匹配文件名
        direct_match_path = os.path.join("static", "md", f"{decoded_doc_id}.md")
        if os.path.exists(direct_match_path):
            file_path = direct_match_path
            logger.info(f"直接匹配找到文档: {direct_match_path}")
        else:
            # 2. 遍历所有文档文件进行匹配
            for md_file in md_files:
                base_name = os.path.basename(md_file)
                file_name_no_ext = os.path.splitext(base_name)[0]
                
                # 精确匹配
                if file_name_no_ext == decoded_doc_id:
                    file_path = md_file
                    logger.info(f"精确匹配找到文档: {md_file}")
                    break
                
                # 不区分大小写匹配
                if file_name_no_ext.lower() == decoded_doc_id.lower():
                    file_path = md_file
                    logger.info(f"不区分大小写匹配找到文档: {md_file}")
                    break
        
        # 如果常规匹配方式未找到文档，尝试更灵活的匹配方式
        if not file_path:
            logger.warning(f"未通过常规方式找到文档 {decoded_doc_id}，尝试更灵活的匹配方式")
            
            # 尝试通过文件名的部分匹配来查找文档
            for md_file in md_files:
                base_name = os.path.basename(md_file)
                file_name_no_ext = os.path.splitext(base_name)[0]
                
                # 检查文档ID是否包含在文件名中，或文件名是否包含在文档ID中
                # 这对于处理URL编码问题特别有用
                if decoded_doc_id in file_name_no_ext or file_name_no_ext in decoded_doc_id:
                    file_path = md_file
                    logger.info(f"通过部分匹配找到文档: {md_file}")
                    break
        
        if not file_path:
            logger.error(f"文档 {decoded_doc_id} 未找到，当前可用文档: {available_docs}")
            raise HTTPException(status_code=404, detail=f"文档 {decoded_doc_id} 不存在")
        
        try:
            # 读取文件内容
            with open(file_path, 'r', encoding='utf-8') as f:
                content = f.read()
            
            # 如果文件内容为空，使用默认内容
            if not content.strip():
                content = """# 测试文档

这是一个用于测试的固定Markdown文本。

## 二级标题

- 列表项1
- 列表项2
- 列表项3

### 三级标题

这是一个表格：

| 列1 | 列2 | 列3 |
|-----|-----|-----|
| 内容1 | 内容2 | 内容3 |
| 数据1 | 数据2 | 数据3 |

```python
# 这是一段代码
print("Hello, World!")
```

> 这是一段引用文本

**粗体文本** 和 *斜体文本*

[链接文本](https://example.com)
"""
                logger.warning(f"文档 {decoded_doc_id} 内容为空，使用默认内容")
            
            # 使用文件名作为标题
            title = os.path.splitext(os.path.basename(file_path))[0] if file_path else "测试文档"
            # 处理文件名，移除数字前缀（如"01_"、"1."等格式）
            import re
            title = re.sub(r'^\d+[_.-]\s*', '', title)
            
            # 将Markdown转换为HTML
            html_content = markdown.markdown(content, extensions=['tables', 'fenced_code'])
            
            logger.info(f"成功加载测试文档 {title}")
            return {
                "id": decoded_doc_id,
                "title": title,
                "content": content,
                "html_content": html_content
            }
        except Exception as e:
            logger.error(f"读取文档 {decoded_doc_id} 失败: {str(e)}")
            raise HTTPException(status_code=500, detail=f"读取文档内容失败: {str(e)}")
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取文档内容失败: {str(e)}")

# 删除以下重复的/content端点实现
# @router.get("/content")
# async def get_document_content_by_query(doc: str):
#     """获取指定文档的内容（通过查询参数）"""
#     try:
#         from utils.logger import logger
#         from urllib.parse import unquote
        
#         # 确保文档ID正确解码（处理中文等非ASCII字符）
#         decoded_doc_id = unquote(doc)
#         logger.info(f"API请求文档内容: 原始ID={doc}, 解码后ID={decoded_doc_id}")
        
#         # 获取所有可用的文档文件
#         import glob
#         md_files = []
        
#         # 尝试使用相对路径（优先）
#         rel_path = os.path.join("static", "md")
#         if os.path.exists(rel_path):
#             md_files = glob.glob(os.path.join(rel_path, "*.md"))
#             logger.info(f"相对路径文档目录存在，包含文件: {[os.path.basename(f) for f in md_files]}")
        
#         # 如果相对路径没有找到文件，尝试使用绝对路径
#         if not md_files:
#             if os.path.exists(DOCS_DIR):
#                 md_files = glob.glob(os.path.join(DOCS_DIR, "*.md"))
#                 logger.info(f"绝对路径文档目录存在，包含文件: {[os.path.basename(f) for f in md_files]}")
        
#         # 记录所有可用文档的文件名（不含扩展名）
#         available_docs = [os.path.splitext(os.path.basename(f))[0] for f in md_files]
#         logger.info(f"可用文档列表: {available_docs}")
        
#         # 尝试查找匹配的文档文件
#         file_path = None
        
#         # 1. 首先尝试直接匹配文件名
#         direct_match_path = os.path.join("static", "md", f"{decoded_doc_id}.md")
#         if os.path.exists(direct_match_path):
#             file_path = direct_match_path
#             logger.info(f"直接匹配找到文档: {direct_match_path}")
#         else:
#             # 2. 遍历所有文档文件进行匹配
#             for md_file in md_files:
#                 base_name = os.path.basename(md_file)
#                 file_name_no_ext = os.path.splitext(base_name)[0]
                
#                 # 精确匹配
#                 if file_name_no_ext == decoded_doc_id:
#                     file_path = md_file
#                     logger.info(f"精确匹配找到文档: {md_file}")
#                     break
                
#                 # 不区分大小写匹配
#                 if file_name_no_ext.lower() == decoded_doc_id.lower():
#                     file_path = md_file
#                     logger.info(f"不区分大小写匹配找到文档: {md_file}")
#                     break
        
#         # 如果常规匹配方式未找到文档，尝试更灵活的匹配方式
#         if not file_path:
#             logger.warning(f"未通过常规方式找到文档 {decoded_doc_id}，尝试更灵活的匹配方式")
            
#             # 尝试通过文件名的部分匹配来查找文档
#             for md_file in md_files:
#                 base_name = os.path.basename(md_file)
#                 file_name_no_ext = os.path.splitext(base_name)[0]
                
#                 # 检查文档ID是否包含在文件名中，或文件名是否包含在文档ID中
#                 # 这对于处理URL编码问题特别有用
#                 if decoded_doc_id in file_name_no_ext or file_name_no_ext in decoded_doc_id:
#                     file_path = md_file
#                     logger.info(f"通过部分匹配找到文档: {md_file}")
#                     break
        
#         if not file_path:
#             logger.error(f"文档 {decoded_doc_id} 未找到，当前可用文档: {available_docs}")
#             raise HTTPException(status_code=404, detail=f"文档 {decoded_doc_id} 不存在")
        
#         try:
#             # 读取文件内容
#             with open(file_path, 'r', encoding='utf-8') as f:
#                 content = f.read()
            
#             # 如果文件内容为空，使用默认内容
#             if not content.strip():
#                 content = """# 测试文档

# 这是一个用于测试的固定Markdown文本。

# ## 二级标题

# - 列表项1
# - 列表项2
# - 列表项3

# ### 三级标题

# 这是一个表格：

# | 列1 | 列2 | 列3 |
# |-----|-----|-----|
# | 内容1 | 内容2 | 内容3 |
# | 数据1 | 数据2 | 数据3 |

# ```python
# # 这是一段代码
# print("Hello, World!")
# ```

# > 这是一段引用文本

# **粗体文本** 和 *斜体文本*

# [链接文本](https://example.com)
# """
#                 logger.warning(f"文档 {decoded_doc_id} 内容为空，使用默认内容")
            
#             # 使用文件名作为标题
#             title = os.path.splitext(os.path.basename(file_path))[0] if file_path else "测试文档"
#             # 处理文件名，移除数字前缀（如"01_"、"1."等格式）
#             import re
#             title = re.sub(r'^\d+[_.-]\s*', '', title)
            
#             # 将Markdown转换为HTML
#             html_content = markdown.markdown(content, extensions=['tables', 'fenced_code'])
            
#             logger.info(f"成功加载测试文档 {title}")
#             return {
#                 "id": decoded_doc_id,
#                 "title": title,
#                 "content": content,
#                 "html_content": html_content
#             }
#         except Exception as e:
#             logger.error(f"读取文档 {decoded_doc_id} 失败: {str(e)}")
#             raise HTTPException(status_code=500, detail=f"读取文档内容失败: {str(e)}")
#     except HTTPException:
#         raise
#     except Exception as e:
#         raise HTTPException(status_code=500, detail=f"获取文档内容失败: {str(e)}")